package com.kamistoat.meimeichat.meimeichatserverapplication.netty.handlers;

import com.alibaba.fastjson.JSON;
import com.kamistoat.meimeichat.meimeichatserverapplication.entity.MmcUserEntity;
import com.kamistoat.meimeichat.meimeichatserverapplication.netty.NettyServerBizHandler;
import com.kamistoat.meimeichat.meimeichatserverapplication.netty.service.NettyUserService;
import com.kamistoat.meimeichat.meimeichatserverapplication.netty.utils.NettyConstants;
import com.kamistoat.meimeichat.meimeichatserverapplication.netty.utils.NettySocketChannelUtil;
import com.kamistoat.meimeichatserveraggrement.protocol.login.ClientOnLineStatusNotice;
import com.kamistoat.meimeichatserveraggrement.protocol.login.LoginRequest;
import com.kamistoat.meimeichatserveraggrement.protocol.login.LoginResponse;
import com.kamistoat.meimeichatserveraggrement.protocol.login.dto.ClientAddressDto;
import com.kamistoat.meimeichatserveraggrement.protocol.login.dto.UserFriendDto;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.net.SocketAddress;
import java.util.List;

/**
 * LoginRequest的Handler
 */
@Component
@ChannelHandler.Sharable
public class LoginHandlerServer extends NettyServerBizHandler<LoginRequest> {
    @Autowired
    NettyUserService nettyUserService;

    /**
     * 登录。暂时简单登录，未加入权限相关
     *
     * @param channel
     * @param loginRequest
     * @Warning:子类只需要重写该方法
     */
    @Override
    public void channelRead(Channel channel, LoginRequest loginRequest) {
        if (loginRequest == null) return;
        logger.info("登录请求处理: " + JSON.toJSONString(loginRequest));
        // 1. TODO 改造登录由此进入
        MmcUserEntity selfUserEntity = nettyUserService.queryUserInfo(loginRequest.getUserId());
        if (selfUserEntity == null || !selfUserEntity.getUserPassword().equals(loginRequest.getUserPassword())) {
            channel.writeAndFlush(new LoginResponse(false));
            return;
        }
        // 验证成功，则获取LoginResponse
        LoginResponse loginResponse = nettyUserService.getLoginResponse(channel, selfUserEntity);

        // 返回响应给发起登录的客户端
        ChannelFuture channelFuture = channel.writeAndFlush(loginResponse);

        if (channelFuture.isSuccess()) {
            logger.info(loginRequest.getUserId() + "-" + loginResponse.getUserNickName() + " 登录成功");
        } else {
            logger.info(loginRequest.getUserId() + "-" + loginResponse.getUserNickName() + " 登录失败，未能将响应返回到Client");
        }
    }

    /**
     * 通道处于Active状态。此时代表BossGroup对于一个新的连接事件，已为其添加所有的handler并分配到一个EventLoop上.
     * 添加进在线用户Map的操作是在LoginHandler和ReConnectHandler中进行的
     *
     * @param ctx
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        logger.info("客户端连接通知：{}", ctx.channel());
    }

    /**
     * 通道处于InActive状态
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        String userChannelId = ctx.channel().id().toString();
        String userId = NettySocketChannelUtil.getUserIdByChannelId(userChannelId);
        if(userId != null && !userId.equals("")){
            // 从所有的Map中删除用户
            NettySocketChannelUtil.removeChannel(userChannelId);
            NettySocketChannelUtil.removeChannelGroupByChannel(ctx.channel());
            NettySocketChannelUtil.USER_ID_P2P_ADDRESS_MAP.remove(userId);

            MmcUserEntity userEntity = nettyUserService.queryUserInfo(userId);
            logger.info(userEntity.getUserNickname() + " 已离线，开始通知其好友");
            // 制作离线通知
            ClientOnLineStatusNotice onLineStatusNotice = new ClientOnLineStatusNotice();
            onLineStatusNotice.setFriendId(userId);
            onLineStatusNotice.setOnLineStatus(NettyConstants.OnLineStatus.OffLine.getCode());
            // 向所有在线好友发送离线通知
            List<UserFriendDto> friendDtoList = nettyUserService.queryUserFriendInfoList(userId);
            for (UserFriendDto friendDto : friendDtoList) {
                Channel onLineFriendChannel = NettySocketChannelUtil.getChannel(friendDto.getFriendId());
                if (onLineFriendChannel != null) {
                    onLineFriendChannel.writeAndFlush(onLineStatusNotice);
                }
            }
            logger.info("已尽力通知 " + userEntity.getUserNickname() + " 的所有在线好友");
        }
        logger.info("客户端下线通知：{}, 已删除服务端所有缓存", ctx.channel());
    }
}























